#pragma once

#include <memory>
#include <iostream>

extern long __auto_id_;

// Define a named mock data class
// It backs copy or move constructing
// T: should be value type, which will be create later
// length: the size of elements will be created later
template<typename T, long lenght = 1024>
class NamedMockData
{
	long _id;
public:
	// Default constructor
	NamedMockData(void) : _data(new T[1024]), _length(lenght), _id(__auto_id_++) {
		// Leave empty
		std::cout << __FUNCTION__ << " Default constructor => " << _id << std::endl;
	}

	// Constructor with injected data, and the owership has been transfered
	explicit NamedMockData(T* data, long size) : _data(data), _length(size), id(__auto_id_++) {
		// Leave empty
		std::cout << __FUNCTION__ << " Constructor with injected data => " << _id << std::endl;
	}

	// Constuct by copying data
	NamedMockData(const NamedMockData& right) : _data(new T[right._length]), 
		_length(right._length), _id(__auto_id_++) {
		std::cout << __FUNCTION__ << " Constuct by copying data => " << _id << std::endl;

		// Need: -D_SCL_SECURE_NO_WARNINGS  compile option
		std::copy(right._data, right._data + right._length, _data);
	}

	// Constucte with moving data
	NamedMockData(NamedMockData&& right) : _data(right._data), _length(right._length), _id(right._id) {
		std::cout << __FUNCTION__ << " Constucte with moving data => " << _id << std::endl;
		
		right._data = nullptr;
		right._length = 0;
	}

	// Assign by coping data
	NamedMockData& operator=(const NamedMockData& right) {
		std::cout << __FUNCTION__ << " Assign by coping data => " << _id << std::endl;

		if (this == &right) return *this;

		delete[] _data; _data = nullptr; _data = new T[right._length];
		std::copy(right._data, right._data + right._length, _data);
		_length = right._length;
		_id = __auto_id_++;

		return *this;
	}

	// Assign by moving data
	NamedMockData& operator=(NamedMockData&& right) {
		std::cout << __FUNCTION__ << " Assign by moving data => " << _id << std::endl;

		if (this == &right) return *this;
		
		delete[] _data; _data = nullptr; _data = std::move(right._data); _id = right._id;

		right._data = nullptr;
		right._length = 0;

		return *this;
	}

	// Virtualized destructor
	virtual ~NamedMockData(void) {
		std::cout << __FUNCTION__ << " => " << _id << std::endl;
		delete[] _data;
	}

	void Print() {
		std::cout << "NamedMockData print something id => " << _id << std::endl;
	}

private:
	T* _data;
	long _length;
};

/// I wrote this sample class, then found another sample is familiar with it,
// You can refere to it, too:
// http://msdn.microsoft.com/en-us/library/dd293665.aspx